package com.ayf.payment.game.api.service.payment;

import com.alibaba.fastjson.JSONObject;
import com.ayf.payment.game.api.bean.BaseResData;
import com.ayf.payment.game.api.channel.jiabei.util.HttpHelper;
import com.ayf.payment.game.api.channel.jiabei.util.StringHelper;
import com.ayf.payment.game.api.config.SystemInitialization;
import com.ayf.payment.game.api.dto.MerchantCommonDTO;
import com.ayf.payment.game.api.dto.OrderAndMerchantDTO;
import com.ayf.payment.game.api.dto.platform.MerchantPaymentProductDTO;
import com.ayf.payment.game.api.dto.platform.PaymentChannelDTO;
import com.ayf.payment.game.api.entity.Order;
import com.ayf.payment.game.api.entity.Partition;
import com.ayf.payment.game.api.exception.NullSetException;
import com.ayf.payment.game.api.httpclient.HttpUtils;
import com.ayf.payment.game.api.service.ChannelTradeAmountRandomRuleService;
import com.ayf.payment.game.api.service.OrderService;
import com.ayf.payment.game.api.type.OrderStatus;
import com.ayf.payment.game.api.utils.BigDecimalUtil;
import com.ayf.payment.game.api.utils.DateUtils;
import com.ayf.payment.game.api.utils.Md5Utils;
import com.ayf.payment.game.api.utils.SnowFlakeUtils;
import com.ayf.payment.game.api.wx.WxSendMsgUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 优卡
 *
 * @author wwl
 * @description:
 * @date 2020/5/13 19:38
 */
@Service
public class YKPaymentService extends IPaymentService {

    private final String agent = "10165";  //代理ID

    @Autowired
    private SystemInitialization systemInitialization;

    @Autowired
    private OrderService orderService;
    @Autowired
    private WxSendMsgUtils wxSendMsgUtils;
    @Autowired
    private ChannelTradeAmountRandomRuleService channelTradeAmountRandomRuleService;

    @Override
    public Map<String, Object> paymentUtil(Order order, Partition partition, String orderCreateStr, String traceId, String redirectUrl) {
        traceId = "优卡创建订单".concat(traceId);
        Map<String, Object> map = new HashMap<>();
        MerchantCommonDTO merchantDTO = merchantService.getMerchantCommon(partition.getMerchantId());
        MerchantPaymentProductDTO merchantPaymentProductDTO = systemInitialization.productDTO(order.getPayTypeId());
        PaymentChannelDTO paymentChannelDTO = systemInitialization.channelDTO(merchantPaymentProductDTO.getcId());
        BigDecimal actualOrderAmt = order.getAmount();
        BigDecimal channelTradeAmountRandomAmt = channelTradeAmountRandomRuleService.getChannelTradeAmountRandomRule(paymentChannelDTO.getId(),order.getAmount());
        actualOrderAmt = actualOrderAmt.add(channelTradeAmountRandomAmt);
        BaseResData baseResData = orderCreate(traceId, order, paymentChannelDTO, redirectUrl, actualOrderAmt, merchantPaymentProductDTO.getBusinessCode(), merchantDTO);
        String orderCreateUrl = "";
        if (baseResData.isProcessing()){
            LogPortal.error("{} 商户ID[{}] 商户订单号[{}] 优卡下单失败 请求接口成功，接口响应超时", traceId, order.getMerchantId(), order.getMerchantOrderNo());
            throw new NullSetException(traceId + "下单失败，请稍后重试！");
        }
        BigDecimal randomAmt = BigDecimal.ZERO;
        order.setRandomAmt(BigDecimal.ZERO);
        if (baseResData.isSuccess()) {
            String rpsData = baseResData.getData();
            JSONObject jsonData = JSONObject.parseObject(rpsData);
            String ret_code = jsonData.getString("ret_code");
            String ret_msg = jsonData.getString("ret_msg");
            if ("00".equals(ret_code)){
                orderCreateUrl = jsonData.getString("ret_url");
                if (StringUtils.isEmpty(orderCreateUrl)){
                    LogPortal.error("{} 商户ID[{}] 商户订单号[{}] 优卡下单失败 请求接口成功，接口返回报文 url为空",traceId,order.getMerchantId(), order.getMerchantOrderNo());
                    throw new NullSetException(traceId + "下单失败，请稍后重试！");
                }
            } else {
                LogPortal.error("{} 商户ID[{}] 商户订单号[{}] 优卡下单失败 请求接口成功，接口返回失败 Code:{} Message:{}",traceId,order.getMerchantId(), order.getMerchantOrderNo(),ret_code,ret_msg);
                throw new NullSetException(traceId + "下单失败，请稍后重试！失败描述："+ret_msg);
            }
        } else {
            LogPortal.error("{} 商户ID[{}] 商户订单号[{}] 优卡下单失败 请求接口失败 Code:{} Message:{}",traceId,order.getMerchantId(), order.getMerchantOrderNo(),baseResData.getRespCode(),baseResData.getRespMsg());
            throw new NullSetException(traceId + "下单失败，请稍后重试！");
        }
        LogPortal.info("{} 商户ID[{}] 商户订单号[{}] 优卡下单 通道支付URL[{}]", traceId, order.getMerchantId(), order.getMerchantOrderNo(),orderCreateUrl);

        order.setRandomAmt(BigDecimal.ZERO);
        order.setOrderNo("");
        order.setPayChannleName(paymentChannelDTO.getName());
        order.setPayChannleId(paymentChannelDTO.getId());
        order.setPayTypeId(merchantPaymentProductDTO.getProductId());
        order.setPayTypeName(merchantPaymentProductDTO.getProductName());
        order.setMerchantIncome(BigDecimal.ZERO);
        order.setPlatformIncome(BigDecimal.ZERO);
        order.setFee(BigDecimal.ZERO);
        order.setChannelIncome(BigDecimal.ZERO);
        orderMapper.insertSelective(order);
        if (StringUtils.isNotEmpty(orderCreateUrl)) {
            redisCacheUtil.setObjectToCacheDelaySeconds(order.getMerchantOrderNo(), orderCreateUrl, 300L);
        }
        map.put("merchantOrderNo", order.getMerchantOrderNo());
        map.put("amount",order.getAmount());
        map.put("randomAmt",BigDecimalUtil.yuanToFen(randomAmt).add(BigDecimalUtil.yuanToFen(actualOrderAmt.subtract(order.getAmount()))));//单位 分
        map.put("rechargeNumber", order.getRechargeNumber());
        map.put("partitionName", order.getPartitionName());
        map.put("code","004");
        map.put("url", orderCreateUrl);
        redisCacheUtil.setObjectToCacheDelaySeconds("PayBean_".concat(order.getMerchantOrderNo()),map, 300L);
        return map;
    }

    private BaseResData orderCreate(String traceId, Order order, PaymentChannelDTO paymentChannelDTO, String redirectUrl, BigDecimal actualOrderAmt, String businessCode,MerchantCommonDTO merchantDTO){
        String methodName = "优卡下单";
        String KeyValue = paymentChannelDTO.getChannelKey();
        String parter = paymentChannelDTO.getAccountNumber();
        String returnUrl=paymentChannelDTO.getReturnUrl();
        String AuthorizationURL = paymentChannelDTO.getPaymentUrl();
        if (StringUtils.isEmpty(AuthorizationURL)){
            LogPortal.error("{} 失败，通道下单地址不能为空，订单号:{}",traceId,order.getMerchantOrderNo());
            throw new NullSetException(traceId + "下单失败，请稍后重试！");
        }
        if (!AuthorizationURL.endsWith("/")){
            AuthorizationURL=AuthorizationURL.concat("/");
        }
        if (StringUtils.isEmpty(returnUrl)){
            LogPortal.error("{} 失败，异步通知地址不能为空，订单号:{}",traceId,order.getMerchantOrderNo());
            throw new NullSetException(traceId + "下单失败，请稍后重试！");
        }
        if (!returnUrl.endsWith("/")){
            returnUrl=returnUrl.concat("/");
        }
        if (!redirectUrl.endsWith("/")){
            redirectUrl=redirectUrl.concat("/");
        }

        AuthorizationURL=AuthorizationURL.concat("gatepaycode/paytransfer");


        StringBuffer dicStr = new StringBuffer();
        dicStr.append("parter=").append(parter);
        dicStr.append("&type=").append(getPayCode(businessCode));
        dicStr.append("&value=").append(actualOrderAmt); //单位元（人民币），2位小数，最小支付金额为0.02
        dicStr.append("&orderid=").append(order.getMerchantOrderNo());
        dicStr.append("&callbackurl=").append(returnUrl + "gameapip/v/yk/pay/notify");

        String sign = Md5Utils.md5(dicStr.toString() + KeyValue);

        dicStr.append("&hrefbackurl=").append(returnUrl + "gameapip/v/yk/pay/returns");
        dicStr.append("&payerIp=").append(order.getClientIp());
        dicStr.append("&attach=").append(redirectUrl);
        dicStr.append("&sign=").append(sign);
        dicStr.append("&agent=").append(agent);
        dicStr.append("&outputType=").append(1);


        LogPortal.info("{} 商户ID[{}] 商户订单号[{}] 下单请求URL[{}]参数[{}]", traceId, order.getMerchantId(), order.getMerchantOrderNo(), AuthorizationURL, dicStr.toString());



        BaseResData baseResData = HttpUtils.sendGet(traceId,methodName,AuthorizationURL + "?" + dicStr,null);

        return baseResData;
    }
    @Override
    public void queryPayOrder(OrderAndMerchantDTO dto, String traceId) {
        LogPortal.error("优卡{} 执行查询订单商户订单号{}", traceId, dto.getMerchantOrderNo());
        try {
            PaymentChannelDTO paymentChannelDTO = systemInitialization.channelDTO(dto.getPayChannleId());
            String KeyValue = paymentChannelDTO.getChannelKey();
            String resultCode = queryCreate(dto.getMerchantId(), dto.getMerchantOrderNo(), traceId,paymentChannelDTO);
            Map<String, String> map = formatResultStr(resultCode);
            if (map.isEmpty()) {
                LogPortal.error("优卡{} 执行查询订单返回参数为空", traceId);
                return;
            }
            String orderid = map.get("orderid");
            String parter = map.get("opstate");
            String ovalue = map.get("ovalue");
            String signVer = MessageFormat.format("orderid={0}&opstate={1}&ovalue={2}{3}", orderid, parter, ovalue, KeyValue);
            String signs= Md5Utils.md5(signVer);
            String sign = map.get("sign");
            if (sign.trim().equals(signs)) {
                Order order = orderService.selectByMerchantOrderNo(orderid);
                if (order == null) {
                    LogPortal.error("优卡查询订单{} 订单号[{}]在我方系统查询不到", traceId, orderid);
                    return;
                }
                OrderStatus orderStatus = OrderStatus.PROCESSING;
                if ("2".equals(parter)) {
                    orderStatus = OrderStatus.FAIL;
                    LogPortal.error("优卡查询订单{} 商户订单号[{}] 签名错误", traceId, orderid);

                }
                if ("0".equals(parter)) {
                    orderStatus = OrderStatus.SUCCESS;
                }
                if (OrderStatus.PROCESSING.equals(order.getOrderStatus()) && !orderStatus.equals(OrderStatus.PROCESSING)) {
                    order.setOrderNo("");
                    order.setOrderStatus(orderStatus);
                    orderService.paymentOrder(order, new JSONObject());
                    if (OrderStatus.SUCCESS.equals(order.getOrderStatus())) {
                        orderService.orderToGetWay(order);
                        wxSendMsgUtils.rechargeSuccess(order);
                    }
                }
            } else {
                LogPortal.error("优卡查询订单{} 订单号[{}]用户还未完成支付或者支付失败", traceId, orderid);
            }
    } catch(Exception e){
        LogPortal.error("优卡查询订单{} 订单号[{}] 异常报错：", e, dto.getMerchantOrderNo());
    }
}

    private Map formatResultStr(String result) {
        Map<String, String> map = new HashMap<>(4);
        String[] strArray1 = result.split("&");
        for (String str : strArray1) {
            String[] strArray = str.split("=");
            map.put(strArray[0], strArray[1]);
        }
        return map;
    }

    private String queryCreate(Integer merId, String orderid, String traceId,PaymentChannelDTO paymentChannelDTO) {
        //商户编号
        String MerhantId = paymentChannelDTO.getAccountNumber();
        //测试商户密钥
        String KeyValue = paymentChannelDTO.getChannelKey();
        String AuthorizationURL = paymentChannelDTO.getPaymentUrl();
        StringBuffer dicStr = new StringBuffer();
        dicStr.append("orderid=").append(orderid);
        dicStr.append("&parter=").append(MerhantId);
        String sign = StringHelper.EncodeMD5(dicStr.toString() + KeyValue);
        dicStr.append("&sign=").append(sign);
        LogPortal.info("优卡{} 商户ID[{}] 商户订单号[{}] 查询订单请求参数[{}]", traceId, merId, orderid, dicStr.toString());
        String result = "";
        try {
            //请求上游接口
            result = HttpHelper.sendPost(AuthorizationURL + "/gateway/search", dicStr.toString(), traceId);
            LogPortal.info("优卡{}查询订单 商户ID[{}] 商户订单号[{}] 返回参数[{}]", traceId, merId, orderid, result);
        } catch (Exception e) {
            LogPortal.error("优卡{}查询订单 商户ID[{}] 商户订单号[{}] 支付渠道查询订单失败，发生了{}异常，错误描述:{}", e, traceId, merId, orderid, e.getClass().getName(), e.getMessage());
        }
        return result;
    }

    private String getPayCode(String code) {

        if ("ALIPAY".equals(code)) {
            return "1003";
        }
        if ("ANTCREDITPAY".equals(code)) {
            return "1003";
        }
        if ("WECHAT".equals(code)) {
            return "1004";
        }
        return "";
    }

    private static void testOrderCreate(){
        PaymentChannelDTO paymentChannelDTO = getTestPaymentChannelDTO();
        Order order = new Order();
        Date currentDate = DateUtils.getNowDate();
        String orderCreateStr = DateUtils.dateToString(currentDate, DateUtils.formatPattern_full_03);
        String orderNo = "M" + orderCreateStr + SnowFlakeUtils.getUniqueId();
        order.setMerchantOrderNo(orderNo);
        order.setCreateTime(currentDate);
        order.setAmount(BigDecimal.valueOf(500));
        order.setMerchantId(1000);
        order.setClientIp("127.0.0.1");
        order.setRechargeNumber("test111");
        order.setPartitionName("111");
        String traceId = SnowFlakeUtils.getTraceId28();
        String redirectUrl = "http://uatxy.po111.cn";
        String bussinessCode = "WECHAT";

        MerchantCommonDTO merchantDTO = new MerchantCommonDTO();
        YKPaymentService xinYou2PaymentService = new YKPaymentService();
        BaseResData baseResData = xinYou2PaymentService.orderCreate(traceId,order,paymentChannelDTO,redirectUrl,order.getAmount(),bussinessCode,merchantDTO);
        System.out.println("优卡下单返回报文:"+ JSONObject.toJSONString(baseResData));
    }

    private static PaymentChannelDTO getTestPaymentChannelDTO(){
        PaymentChannelDTO paymentChannelDTO = new PaymentChannelDTO();
        paymentChannelDTO.setPaymentUrl("https://sdk.7uka.com");
        paymentChannelDTO.setReturnUrl("http://uatxy.111ao.cn");
        paymentChannelDTO.setChannelKey("414a30ba38e5430e8aec0e4f6ad9f7db");
        paymentChannelDTO.setAccountNumber("100114");// 商户ID
        return paymentChannelDTO;
    }

    public static void main(String[] args) {
        testOrderCreate();
    }
}
